package com.briup.corejava.day16;

/**
 * 线程通信案例：吃包子 -> 两条线程
 * wait
 * notify
 * 上面两个方法只能由锁对象在同步代码块或者同步方法中调用
 */
public class Test4 {
    public static void main(String[] args) {
        // 准备一个锁对象
        Plate plate = new Plate();
        // 厨师
        Thread t1 = new Producer(plate,"厨师");
        // 顾客1
        Thread t2 = new Consumer(plate,"tom");
        // 顾客2
        Thread t3 = new Consumer2(plate,"jerry");
        t1.start();
        t2.start();
        t3.start();
    }
}
// 提供锁对象的类
class Plate{
    int num;
    // boolean flag; // 代表是否有包子，默认为false
    int flag;// 三个线程，一个生产，两个消费，提供三个标识
}
// 生产者线程 -》 新增包子数量
class Producer extends Thread{
    private final Plate plate;
    public Producer(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            synchronized (plate){
                // 判断，如果有包子，不需要生产，该线程等待
                while(plate.flag!=0){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 如果没有包子，进行生产
                String name = Thread.currentThread().getName();
                System.out.println(name+"正在第"+i+"次生产包子...");
                // 数据改变
                System.out.println("生产完成，共有"+(plate.num+=2)+"个包子，快来吃");
                // 改变旗标，唤醒第一个顾客
                plate.flag = 1;
                // 唤醒等待池中的线程
                plate.notifyAll();
            }
        }
    }
}
// 消费者线程 -》 减少包子数量
class Consumer extends Thread{
    private final Plate plate;
    public Consumer(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            synchronized (plate){
                // 判断，如果没有包子，没的吃了，该线程等待
                while(plate.flag!=1){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 如果有包子，进行消费
                String name = Thread.currentThread().getName();
                System.out.println(name+"正在吃第"+i+"个包子...");
                // 数据改变
                System.out.println("吃完了，还剩"+(--plate.num)+"个包子");

                plate.flag = 2;
                // 唤醒等待池中的线程
                plate.notifyAll();
            }
        }
    }
}
class Consumer2 extends Thread{
    private final Plate plate;
    public Consumer2(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            synchronized (plate){
                // 判断，如果没有包子，没的吃了，该线程等待
                while (plate.flag!=2){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 如果有包子，进行消费
                String name = Thread.currentThread().getName();
                System.out.println(name+"正在吃第"+i+"个包子...");
                // 数据改变
                System.out.println("吃完了，还剩"+(--plate.num)+"个包子");
                plate.flag = 0;
                // 唤醒等待池中的线程
                plate.notifyAll();
            }
        }
    }
}